package model

import (
	"database/sql"
	"fmt"
	"github.com/jmoiron/sqlx"
	"time"
	"zimuzu_cvn_web_api/config"
	. "zimuzu_cvn_web_api/pkg/e"
)

const (
	LogSourceAirdrop                     = 1   //空投奖励
	LogSourceRouter                      = 2   //路由器挖矿收益
	LogSourceOut                         = 3   //转账
	LogSourceOutFee                      = 4   //转账手续费
	LogSourceTransferFailBack            = 5   //转账失败返还
	LogSourcePledge                      = 7   //质押
	LogSourcePledgeRedemption            = 8   //质押赎回
	LogSourceSystemIncrease              = 10  //系统增加
	LogSourceSystemDeduction             = 11  //系统扣除
	LogSourceLX                          = 12  //奖励池
	LogSourceIn                          = 13  //收款
	LogSourceShopping                    = 14  //商城消费
	LogSourceRebate                      = 15  //返佣
	LogSourceInnerOut                    = 16  //站内转账
	LogSourceInnerIn                     = 17  //站内收款
	LogSourcePledgeRouter                = 18  //路由器质押
	LogSourcePledgeRedemptionRouter      = 19  //路由器质押赎回
	LogSourceSuperNodePledge             = 20  //超级节点质押
	LogSourceSuperNodePledgeRedemption   = 21  //超级节点质押赎回
	LogSourceSuperNodeMinerIncome        = 22  //超级节点矿工分红
	LogSourceSuperNodeAwardIncome        = 23  //超级节点首年奖励
	LogSourceSystemRecharge              = 24  //系统充值
	LogSourcePledgePC                    = 25  //PC质押
	LogSourcePledgeRedemptionPC          = 26  //PC质押赎回
	LogSourcePC                          = 27  //PC挖矿收益
	LogSourceExchangeVipCode             = 28  //兑换金至尊
	LogSourceBeAgent                     = 29  //购买经销商
	LogSourceRouterAward                 = 30  //第三批路由器奖励
	LogSourceBuyToken                    = 31  //令牌购买
	LogSourceSaleToken                   = 32  //令牌回购
	LogSourceSystemAddDeposit            = 33  //系统补充保证金
	LogSourcePledgeDeposit               = 34  //保证金质押
	LogSourceDepositToken                = 35  //保证金提取
	LogSourceTokenLend                   = 36  //令牌出租收益
	LogSourceTokenRent                   = 37  //令牌租用扣款
	LogSourceSystemDeductDeposit         = 38  //保证金划转至余额
	LogSourceInitTokenBack               = 39  //初始化令牌退还
	LogSourceSuperNodeDeleteForSuperNode = 40  //超级节点强制删除矿工支付的赔偿金
	LogSourceSuperNodeDeleteForMiner     = 41  //矿工被强制删除获得的赔偿金
	LogSourceSuperNodeExitForMiner       = 42  //退出超级节点赔偿金
	LogSourceSuperNodeExitForSuperNode   = 43  //退出超级节点补偿金
	LogSourceSystemSupplyDeposit         = 44  //令牌租用扣款
	LogSourceRechargeYTABack             = 45  //兑换YTA退回
	LogSourceSystemRechargeYTA           = 46  //兑换YTA
	LogSourceSystemBalancing             = 100 //系统平账
)

var (
	CvnLogSourceAmountInc       = []int{1, 2, 5, 8, 10, 12, 13, 15, 17, 19, 21, 22, 23, 24, 26, 27, 30, 32, 35, 36, 38, 39, 41, 43, 45, 100}
	CvnLogSourceAmountDec       = []int{3, 4, 7, 11, 14, 16, 18, 20, 25, 28, 29, 31, 33, 34, 37, 40, 42, 44, 46}
	CvnLogSourceFrozenAmountInc = []int{18, 20, 25, 33, 34}
	CvnLogSourceFrozenAmountDec = []int{19, 21, 26, 38, 35}
)

type CvnLogDb struct {
	Id               int64   `db:"id" json:"id"`
	Uid              int64   `db:"uid" json:"uid"`
	Amount           float64 `db:"amount" json:"amount"`
	Balance          float64 `db:"balance" json:"balance"`
	RelateId         string  `db:"relate_id" json:"relate_id"`
	RelateTable      string  `db:"relate_table" json:"relate_table"`
	From             string  `db:"from" json:"from"`
	To               string  `db:"to" json:"to"`
	TxHash           string  `db:"txhash" json:"txhash"`
	Source           int     `db:"source" json:"source"`
	Status           int     `db:"status" json:"status"`
	CreateTime       int64   `db:"create_time" json:"create_time"`
	UpdateTime       int64   `db:"update_time" json:"update_time"`
	Block            int64   `db:"block" json:"block"`
	BlockConfirmTime int64   `db:"block_confirm_time" json:"block_confirm_time"`
	SignString       string  `db:"sign_string" json:"sign_string"`
	SignVersion      string  `db:"sign_version" json:"sign_version"`
}

//全部转账记录
type TransferLogRes struct {
	Id         int64   `db:"id" json:"id"`
	Uid        int64   `db:"uid" json:"uid"`
	Amount     float64 `db:"amount" json:"amount"`
	Source     int     `db:"source" json:"source"`
	Status     int     `db:"status" json:"status"`
	CreateTime string  `db:"create_time" json:"create_time"`
}

//插入记录
func AddCvnLog(db sqlx.Execer, data CvnLogDb) (id int64, err error) {
	data.TxHash = Trim(data.TxHash)
	data.CreateTime = time.Now().Unix()
	data.UpdateTime = time.Now().Unix()
	if data.Status == 0 {
		data.Status = 1
	}
	result, err := db.Exec("INSERT INTO cvn_log (uid,amount,balance,relate_id,relate_table,txhash,`from`,`to`,source,status,create_time,update_time,block,block_confirm_time,sign_string,sign_version) VALUES (?, ?, ?, ?, ?, if(? = '', null, ?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
		data.Uid, data.Amount, data.Balance, data.RelateId, data.RelateTable, data.TxHash, data.TxHash, data.From, data.To, data.Source, data.Status, data.CreateTime, data.UpdateTime, data.Block, data.BlockConfirmTime, data.SignString, data.SignVersion)
	if err != nil {
		Log("err", err)
		return 0, err
	}
	id, err = result.LastInsertId()
	if err != nil {
		Log("err", err)
		return 0, err
	}
	return id, nil
}

//修改记录：状态
func UpdateCvnLogStatus(db sqlx.Execer, data CvnLogDb) (err error) {
	data.UpdateTime = time.Now().Unix()
	_, err = db.Exec(`update cvn_log SET txhash = if(? = "", null, ?), status = ?, block = ?, block_confirm_time = ?, update_time = ? WHERE id = ?`,
		data.TxHash, data.TxHash, data.Status, data.Block, data.BlockConfirmTime, data.UpdateTime, data.Id)
	if err != nil {
		Log("err", err)
	}
	return err
}

//修改记录：签名
func UpdateCvnLogSign(db sqlx.Execer, logid int64, signString, signVersion string) (err error) {
	_, err = db.Exec("update cvn_log set sign_string = ?, sign_version = ? where id = ?", signString, signVersion, logid)
	if err != nil {
		Log("err", err)
	}
	return err
}

//获取列表：转账中
func GetCvnLogWaitList(db sqlx.Queryer) (qi []CvnLogDb, err error) {
	err = sqlx.Select(db, &qi, "SELECT id,uid,amount,`from`,`to`,source,status,create_time FROM cvn_log where source = ? AND status = ? ORDER BY id ASC", LogSourceOut, DealStatusCheck)
	if err != nil {
		Log("err", err)
	}
	return qi, err
}

//获取列表：uid
func GetCvnLogListByUid(db sqlx.Queryer, uid int64) (qi []CvnLogDb, err error) {
	err = sqlx.Select(db, &qi, "select id,uid,amount,balance,relate_id,relate_table,`from`,`to`,source,sign_string,sign_version from cvn_log where uid = ? order by id desc", uid)
	if err != nil {
		Log("err", err)
	}
	return qi, err
}

//单条记录
func GetCvnLog(db sqlx.Queryer, id int64) (qi CvnLogDb, err error) {
	err = sqlx.Get(db, &qi, "select id,uid,amount,balance,relate_id,relate_table,`from`,`to`,IFNULL(txhash,'') as txhash,source,status,create_time,update_time,block,block_confirm_time,sign_string,sign_version from cvn_log where id = ?", id)
	if err != nil {
		Log("err", err)
	}
	return qi, err
}

//获取最后一条日志签名
func GetLastCvnLogSign(db sqlx.Queryer, uid int64) (sign DbSign, err error) {
	err = sqlx.Get(db, &sign, "select sign_string,sign_version from cvn_log where uid = ? order by id desc limit 1", uid)
	if err == sql.ErrNoRows {
		err = nil
	}
	if err != nil {
		Log("err", err)
	}
	return sign, err
}

//获取手续费
func GetCvnLogCharge(db sqlx.Queryer, id int64) (charge float64, err error) {
	err = sqlx.Get(db, &charge, "SELECT amount FROM cvn_log WHERE relate_id = ? and source = ?", id, LogSourceOutFee)
	if err != nil {
		Log("err", err)
	}
	return charge, err
}

//TxHash是否存在
func ExistCvnLogTxHash(db sqlx.Queryer, txHash string) (bool, error) {
	var count int
	err := sqlx.Get(db, &count, "SELECT count(*) FROM cvn_log WHERE txhash = ?", txHash)
	if err != nil {
		Log("err", err)
		return false, err
	}
	if count == 0 {
		return false, nil
	}
	return true, nil
}

//检查关联记录是否存在
func ExistCvnLogRelated(db sqlx.Queryer, relateId string, source int) (bool, error) {
	var count int
	err := sqlx.Get(db, &count, "SELECT count(*) FROM cvn_log where relate_id = ? and source = ?", relateId, source)
	if err != nil {
		Log("err", err)
		return false, err
	}
	if count == 0 {
		return false, nil
	}
	return true, nil
}

//查询某种来源的金额
func SumCvnLogSource(db sqlx.Queryer, uid int64, source int, day int64) (sum float64, err error) {
	t := time.Now().Unix() - day*TimeFormatDay
	sqlStr := "SELECT IFNULL(sum(amount),0) as amount FROM cvn_log WHERE uid = ? "
	if source > 0 {
		sqlStr += fmt.Sprintf("and source = %d ", source)
	}
	if day > 0 {
		sqlStr += fmt.Sprintf("and create_time >= %d ", t)
	}
	err = sqlx.Get(db, &sum, sqlStr, uid)
	if err != nil {
		Log("err", err)
		return 0, err
	}
	return sum, err
}

func GetTransferLog(page, per, status int, targetUid int) (res []TransferLogRes, err error) {
	start := (page - 1) * per
	sqlStr := "select id, uid, amount, source, status, FROM_UNIXTIME(create_time, '%Y/%m/%d %H:%i:%s') AS create_time from cvn_log where source IN (3, 13, 16, 17) "

	if status > 0 {
		sqlStr += fmt.Sprintf("AND status = %d ", status)
	}
	if targetUid > 0 {
		sqlStr += fmt.Sprintf("AND uid = %d ", targetUid)
	}
	sqlStr += fmt.Sprintf("ORDER BY id DESC LIMIT %d, %d", start, per)
	err = sqlx.Select(config.C.DB.DB, &res, sqlStr)
	if err != nil {
		Log("GetTransferLog: ", err.Error())
	}
	return
}

func GetUsdtTransferLog(page, per, status int, targetUid int) (res []TransferLogRes, err error) {
	start := (page - 1) * per
	sqlStr := "select id, uid, amount, source, status, FROM_UNIXTIME(create_time, '%Y/%m/%d %H:%i:%s') AS create_time from usdt_log where source IN (101, 102, 201, 202) "

	if status > 0 {
		sqlStr += fmt.Sprintf("AND status = %d ", status)
	}
	if targetUid > 0 {
		sqlStr += fmt.Sprintf("AND uid = %d ", targetUid)
	}
	sqlStr += fmt.Sprintf("ORDER BY id DESC LIMIT %d, %d", start, per)
	err = sqlx.Select(config.C.DB.DB, &res, sqlStr)
	if err != nil {
		Log("GetTransferLog: ", err.Error())
	}
	return
}

func GetTransferLogCount(status int, targetUid int) (int, error) {
	var count sql.NullInt64
	sqlStr := "select count(*) from cvn_log where source IN (3, 13, 16, 17) "
	if status > 0 {
		sqlStr += fmt.Sprintf("AND status = %d ", status)
	}
	if targetUid > 0 {
		sqlStr += fmt.Sprintf("AND uid = %d ", targetUid)
	}
	err := sqlx.Get(config.C.DB.DB, &count, sqlStr)
	if err != nil {
		Log("err", "GetTransferLogCount 失败", err.Error())
	}
	return Int64ToInt(count.Int64), err
}

func GetUsdtTransferLogCount(status int, targetUid int) (int, error) {
	var count sql.NullInt64
	sqlStr := "select count(*) from usdt_log where source IN (101, 102, 201, 202) "
	if status > 0 {
		sqlStr += fmt.Sprintf("AND status = %d ", status)
	}
	if targetUid > 0 {
		sqlStr += fmt.Sprintf("AND uid = %d ", targetUid)
	}
	err := sqlx.Get(config.C.DB.DB, &count, sqlStr)
	if err != nil {
		Log("err", "GetUsdtTransferLogCount 失败", err.Error())
	}
	return Int64ToInt(count.Int64), err
}

//查询Cvn累计提现金额
func GetWithdrawTotalCvn() (count float64, err error) {
	err = sqlx.Get(config.C.DB.DB, &count, "select -sum(amount) from cvn_log where source = 3 and status = 1")
	if err != nil {
		Log("err", "查询累计提现信息失败:", err.Error())
	}
	return
}

type CvnLogAdminStatistjcsRes struct {
	WithdrawToday float64 `db:"withdrawToday" json:"withdrawToday"`
	ExamineToday  float64 `db:"examineToday" json:"examineToday"`
	RechargeToday float64 `db:"rechargeToday" json:"rechargeToday"`
	Date          string  `db:"date" json:"date"`
}

//管理后台CVN流水统计
func CvnLogAdminStatistjcs(page, per int) (res []CvnLogAdminStatistjcsRes, err error) {
	start := (page - 1) * per
	err = sqlx.Select(config.C.DB.DB, &res, ""+
		"select date ,sum(withdrawToday) withdrawToday, sum(rechargeToday) rechargeToday, sum(examineToday) examineToday   from ((select FROM_UNIXTIME(l.create_time,'%Y-%m-%d') date, -sum(if(source=3,amount,0)) withdrawToday,sum(if(source=13,amount,0)) rechargeToday  ,0 examineToday from cvn_log l  where (source = 3 or source = 13)  AND  l.create_time > unix_timestamp(now()) - ?*3600*24 GROUP BY FROM_UNIXTIME(l.create_time,'%Y-%m-%d') ORDER BY  l.create_time DESC)"+
		"UNION ALL"+

		"(select FROM_UNIXTIME(e.examine_time,'%Y-%m-%d') date, 0 withdrawToday,0 rechargeToday  ,-sum(if(source=3&&e.status=1,amount,0)) examineToday from cvn_log l  INNER JOIN cvn_examine e ON e.log_id = l.id and e.status = 1 where (source = 3 or source = 13)  AND  l.create_time > unix_timestamp(now()) - ?*3600*24 GROUP BY FROM_UNIXTIME(e.examine_time,'%Y-%m-%d') ORDER BY  l.create_time DESC )) a GROUP BY date ORDER BY date DESC limit ?, ?", per, per, start, per)
	if err != nil {
		Log("CvnLogAdminStatistjcs: ", err.Error())
	}
	return
}

type CvnLogRechargeDaylyRes struct {
	Date   string  `db:"time" json:"time"`
	Amount float64 `json:"value" db:"value"`
}

//管理后台CVN流水统计
func CvnLogRechargeDayly(page, per int) (res []CvnLogRechargeDaylyRes, err error) {
	start := (page - 1) * per
	err = sqlx.Select(config.C.DB.DB, &res, " select FROM_UNIXTIME(create_time,'%Y-%m-%d') time, sum(amount) value from cvn_log where status = 1 and source = 13 GROUP BY FROM_UNIXTIME(create_time,'%Y-%m-%d') ORDER BY  create_time DESC limit ? , ?", start, per)
	if err != nil {
		Log("CvnLogRechargeDayly: ", err.Error())
	}
	return
}
